package com.platform.core.web.controller;

import com.platform.aspect.WebLog;
import com.platform.comm.exceptions.FeignApiException;
import com.platform.comm.feign.InternalAPI;
import com.platform.comm.validation.groups.Insert;
import com.platform.comm.validation.groups.Modify;
import com.platform.core.service.SysFunctionService;
import com.platform.dto.FunctionQo;
import com.platform.dto.FunctionTreeNode;
import com.platform.dto.MenuTree;
import com.platform.enums.FunctionStatus;
import com.querydsl.core.BooleanBuilder;
import com.platform.comm.web.results.DataJsonResult;
import com.platform.comm.web.results.JsonResult;
import com.platform.comm.web.results.PageListJsonResult;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;


/**
 * Description: 菜单管理
 *
 * @author coder
 */
@RestController
@RequestMapping("/management/function")
public class SysFunctionController extends BaseController {

    private final SysFunctionService sysFunctionService;

    public SysFunctionController(SysFunctionService sysFunctionService) {
        this.sysFunctionService = sysFunctionService;
    }

    @WebLog(theme = "新增[菜单]", moduleName = "菜单管理", type = WebLog.OpType.ADD, root = FunctionQo.class)
    @PostMapping(name = "新增菜单", path = "create")
    public JsonResult create(@Validated({Insert.class}) @RequestBody FunctionQo functionQo) {
        return createOrModifyWithResult(sysFunctionService::create, functionQo);
    }

    @InternalAPI
    @WebLog(theme = "新增[菜单]", moduleName = "菜单管理", type = WebLog.OpType.ADD, root = FunctionQo.class)
    @PostMapping(name = "新增菜单", path = "api/create")
    public FunctionQo createApi(@Validated({Insert.class}) @RequestBody FunctionQo functionQo) {
        try {
            return sysFunctionService.create(functionQo);
        } catch (Exception ex) {
            throw new FeignApiException(ex.getMessage());
        }
    }

    @WebLog(theme = "修改[菜单]", moduleName = "菜单管理", type = WebLog.OpType.MOD, root = FunctionQo.class)
    @PostMapping(name = "修改菜单", path = "modify")
    public JsonResult modify(@Validated({Modify.class}) @RequestBody FunctionQo functionQo) {
        return createOrModifyWithResult(sysFunctionService::modify, functionQo);
    }

    @InternalAPI
    @PostMapping(name = "修改菜单", path = "api/modify")
    @WebLog(theme = "修改[菜单]", moduleName = "菜单管理", type = WebLog.OpType.MOD, root = FunctionQo.class)
    public FunctionQo modifyApi(@Validated({Insert.class}) @RequestBody FunctionQo functionQo) {
        try {
            return sysFunctionService.modify(functionQo);
        } catch (Exception ex) {
            throw new FeignApiException(ex.getMessage());
        }
    }


    @PostMapping(name = "删除菜单", path = "remove")
    @WebLog(theme = "删除[菜单]", moduleName = "菜单管理", type = WebLog.OpType.DEL, root = FunctionQo.class)
    public JsonResult remove(@RequestBody FunctionQo functionQo) {
        return removeOrOtherByIds(sysFunctionService::remove, functionQo.getId());
    }

    @InternalAPI
    @WebLog(theme = "修改[菜单]", moduleName = "菜单管理", type = WebLog.OpType.DEL, root = FunctionQo.class)
    @PostMapping(name = "删除菜单", path = "api/remove")
    public void removeApi(@RequestBody FunctionQo functionQo) {
        sysFunctionService.remove(functionQo.getId());
    }

    @PostMapping(name = "批量删除菜单", path = "batchRemove")
    @WebLog(theme = "批量删除[菜单]", moduleName = "菜单管理", type = WebLog.OpType.DEL_BATCH, root = List.class)
    public JsonResult batchRemove(@RequestBody List<String> ids) {
        return removeOrOtherByIds(sysFunctionService::batchRemove, ids);
    }

    @PostMapping(name = "启用禁用菜单", path = "changeFlag")
    @WebLog(theme = "启用禁用[菜单]", moduleName = "菜单管理", type = WebLog.OpType.MOD, root = Map.class)
    public JsonResult changeFlag(@RequestBody Map<String, Object> parametersMap) {
        FunctionStatus ynEnum = FunctionStatus.parse(parametersMap.get("flag").toString());
        List<String> ids = (List<String>) parametersMap.get("ids");
        return change(sysFunctionService::changeFlag, ids, ynEnum);
    }

    @PostMapping(name = "启用禁用菜单", path = "api/changeFlag")
    @WebLog(theme = "启用禁用[菜单]", moduleName = "菜单管理", type = WebLog.OpType.MOD, root = Map.class)
    public void changeFlagApi(@RequestBody Map<String, Object> parametersMap) {
        FunctionStatus ynEnum = FunctionStatus.parse(parametersMap.get("flag").toString());
        List<String> ids = (List<String>) parametersMap.get("ids");
        sysFunctionService.changeFlag(ids, ynEnum);
    }

    @PostMapping(name = "分页查询菜单", path = "search")
    public PageListJsonResult<FunctionQo> search(@RequestBody Map<String, String> parametersMap) {
        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
        parametersMap.forEach(parameters::add);
        return queryByPaging(sysFunctionService::queryFunctions, new BooleanBuilder(), getPageable(parametersMap), parameters);
    }

    @PostMapping(name = "加载菜单树", path = "tree")
    public DataJsonResult<FunctionTreeNode> tree() {
        return query(sysFunctionService::loadAllFunction);
    }

    @PostMapping(name = "加载菜单树", path = "api/treeByApp")
    public FunctionTreeNode treeByApp(@RequestBody Map<String, String> parametersMap) {
        return sysFunctionService.loadAllFunctionByApp(parametersMap.get("appCode"));
    }

    @PostMapping(name = "菜单预览", path = "api/previewByApp")
    public FunctionTreeNode previewByApp(@RequestBody Map<String, String> parametersMap) {
        return sysFunctionService.previewByApp(parametersMap.get("appCode"));
    }


    @PostMapping(name = "根据Id查询菜单详情", path = "detail")
    public DataJsonResult<FunctionQo> detail(@RequestBody FunctionQo functionQo) {
        return query(sysFunctionService::queryWithPermissions, functionQo.getId());
    }

    @PostMapping(name = "根据Id查询菜单详情", path = "api/detail")
    public FunctionQo detailApi(@RequestBody Map<String, String> parametersMap) {
        return sysFunctionService.queryWithPermissions(parametersMap.get("id"));
    }

    @PostMapping(name = "加载菜单树", path = "treeAll")
    public DataJsonResult<FunctionTreeNode> treeAll(@RequestBody Map<String, String> parametersMap) {
        return query(sysFunctionService::treeAll, parametersMap.get("roleId"));
    }

    @PostMapping(name = "根据subSystemCode查找菜单", path = "api/code")
    public FunctionQo queryBySubSystemCode(@RequestBody Map<String, String> parametersMap) {
        return this.sysFunctionService.queryBySubSystemCode(parametersMap.get("code"));
    }

    @PostMapping(name = "根据subSystemId查找菜单", path = "api/id")
    public FunctionQo queryBySubSystemId(@RequestBody Map<String, String> parametersMap) {
        return this.sysFunctionService.queryBySubSystemId(parametersMap.get("id"));
    }

    @PostMapping(name = "检查同一父级菜单下菜单名称是否存在", path = "checkMenuNameExists")
    public DataJsonResult<Boolean> checkMenuNameExists(@RequestBody Map<String, String> parametersMap) {

        String id = parametersMap.get("id");
        String parentId = parametersMap.get("parentId");
        String menuName = parametersMap.get("menuName");
        return DataJsonResult.succeed(sysFunctionService.checkMenuNameIsExist(id, menuName, parentId));
    }

    @PostMapping(name = "加载权限菜单树", path = "treeByAuthorize")
    public DataJsonResult<List<MenuTree>> treeByAuthorize(@RequestBody(required = false) Map<String, Boolean> param) {
        return DataJsonResult.succeed(sysFunctionService.treeByAuthorizes(param));
    }

    @PostMapping(name = "加载低代码权限菜单树", path = "/treeByAuthorizeLowcode")
    public DataJsonResult<List<MenuTree>> treeByAuthorizeByLowcode(@RequestBody(required = false) Map<String, String> param) {
        return DataJsonResult.succeed(sysFunctionService.treeByAuthorizesLowcode(param));
    }

    @PostMapping(name = "根据条件查询菜单数量", path = "api/count")
    long searchCount(@RequestBody Map<String, String> parametersMap) {
        return this.sysFunctionService.searchCount(parametersMap);
    }

    @PostMapping(name = "根据bizType、funcPath查询是否被有效菜单使用", path = "api/isUsedByFuncPath")
    public boolean isUsedByFuncPath(@RequestBody Map<String, String> parametersMap) {
        return this.sysFunctionService.isUsedByFuncPath(parametersMap);
    }

    @PostMapping(name = "根据路由删除相关的所有菜单", path = "api/removeByRoute")
    @WebLog(theme = "根据路由删除相关的所有[菜单]", moduleName = "菜单管理", type = WebLog.OpType.DEL_BATCH, root = FunctionQo.class)
    public void removeByRoute(@RequestBody FunctionQo functionQo) {
        this.sysFunctionService.removeByRoute(functionQo);
    }

    @PostMapping(name = "根据条件查询菜单信息集合，返回list", path = "api/searchFunctionByCodeAndBizType")
    public List<FunctionQo> searchFunctionByCodeAndBizType(@RequestBody Map<String, String> parametersMap) {
        return this.sysFunctionService.searchFunctionByCodeAndBizType(parametersMap);
    }

    @PostMapping(name = "根据条件查询菜单信息集合，返回list", path = "init/routeCode")
    public JsonResult initRouteCode() {
        this.sysFunctionService.initRouteCode();
        return JsonResult.success();
    }

}
